package cn.baiweigang.uu.service.linearswap;

import cn.baiweigang.uu.enums.StrategyStatusEnum;
import cn.baiweigang.uu.enums.TradeStatusEnum;
import cn.baiweigang.uu.model.KLineInfo;
import cn.baiweigang.uu.model.StrategyInfo;
import cn.baiweigang.uu.model.SummarySheetInfo;
import cn.baiweigang.uu.service.DbService;
import cn.baiweigang.uu.utils.DateUtil;
import cn.baiweigang.uu.utils.LogUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class RiskService {
    @Autowired
    private StrategyService strategyService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private DbService dbService;

    public void checkRiskForPosition(StrategyInfo strategyInfo, KLineInfo kLineInfo) {
        LogUtil.logInfo("持仓风险检查--");
        try {
            //异常防护
            if (strategyInfo.getOpenOrder() == null || strategyInfo.getOpenOrder().getStatus() != TradeStatusEnum.ALL_DEAL) {
                String memo = "当前没有持仓订单信息 出现异常了  需要从头开始";
                LogUtil.logError(memo);
                strategyService.advance(strategyInfo, StrategyStatusEnum.INIT, memo);
                return;
            }
            //当前持仓时间
            long holdTs = DateUtil.getTs() - strategyInfo.getOrderDealTs();
            //持仓时间超过最大时间 强平
            if (strategyInfo.getOpenOrder().getStatus() == TradeStatusEnum.ALL_DEAL &&
                    holdTs > strategyInfo.getPositionMaxMinutes() * 60 * 1000) {
                String forceCloseMemo = "持仓超过最大时间，需要强制平仓";
                LogUtil.logError(forceCloseMemo);
                strategyInfo.setForceCloseMemo(forceCloseMemo);
                orderService.forceCleanPosition(strategyInfo.getOpenOrder());
                return;
            }
            KLineInfo pre = strategyInfo.getKLineList().get(4);
            //5分钟内订单变化大于1000 强平
            if (kLineInfo.getClose().subtract(pre.getLow()).abs().doubleValue() >= strategyInfo.getChangeMaxVolume()) {
                String forceCloseMemo = "5分钟内价格变化大于 " + strategyInfo.getChangeMaxVolume() + " 需要强制平仓";
                LogUtil.logError(forceCloseMemo);
                strategyInfo.setForceCloseMemo(forceCloseMemo);
                orderService.forceCleanPosition(strategyInfo.getOpenOrder());
                //暂停30分钟开仓
                strategyInfo.setAllowNextOpenTs(DateUtil.getTs() + 30 * 60 * 1000);
                return;
            }
            LogUtil.logInfo("当前持仓无风险");
        } catch (Throwable e) {
            LogUtil.logError("风险检查处理异常 " + e.getMessage());
        }
    }


    public void checkRiskAfterEnd(StrategyInfo strategyInfo) {
        LogUtil.logInfo("一轮结束后，风险检查");
        try {
            //当前盈亏总点数 是否大于允许亏损点数
            SummarySheetInfo summarySheetInfo = strategyInfo.getSummarySheetInfo();
            double profitVolume = 0;
            if (summarySheetInfo != null) {
                profitVolume = strategyInfo.getSummarySheetInfo().getProfitVolume();
            }
            //当天亏损超过设置值
            if (profitVolume < strategyInfo.getDay1SlMaxVolume()) {
                LogUtil.logInfo("当天总盈亏=" + profitVolume + " 超过配置的最大值=" + strategyInfo.getDay1SlMaxVolume() +
                        " 当天暂停开仓");
                //第2天0点后再开仓
                strategyInfo.setAllowNextOpenTs(DateUtil.getTs() + DateUtil.getNextDay0() * 60 * 1000);
                return;
            }

            //出现单笔亏损超过400 暂停2小时
            if (strategyInfo.getCloseOrder().getRealProfit().doubleValue() < 0 &&
                    strategyInfo.getCloseOrder().getTradeAvgPrice().subtract(
                            strategyInfo.getOpenOrder().getTradeAvgPrice()).abs().doubleValue() > 400) {
                LogUtil.logInfo("当前这笔亏损超过400 暂停一个周期再开仓");
                //2小时后再开仓
                strategyInfo.setAllowNextOpenTs(DateUtil.getTs() + strategyInfo.getPositionMaxMinutes() * 60 * 1000);
                return;
            }

            //出现连续2笔亏损  暂停2小时
            if (dbService.queryAlwaysSlNum(strategyInfo.getAccountInfo()) >= 2) {
                LogUtil.logInfo("当前连续亏损2笔 暂停一个周期再开仓");
                //2小时后再开仓
                strategyInfo.setAllowNextOpenTs(DateUtil.getTs() + strategyInfo.getPositionMaxMinutes() * 60 * 1000);
                return;
            }
            LogUtil.logInfo("无风险，继续下一轮");
        } catch (Throwable e) {
            LogUtil.logError("风险检查处理异常 " + e.getMessage());
        }

    }
}
